package com.wayne.security.config;

import com.wayne.security.provider.MyAuthenticationProvider;
import com.wayne.security.service.MyUserDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.session.HttpSessionEventPublisher;

import javax.annotation.Resource;
import java.util.Arrays;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Resource
  private MyUserDetailsService userService;

  @Resource
  MyWebAuthenticationDetailsSource myWebAuthenticationDetailsSource;

  @Bean
  PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userService);
  }

  @Bean
  MyAuthenticationProvider myAuthenticationProvider() {
    MyAuthenticationProvider myAuthenticationProvider = new MyAuthenticationProvider();
    myAuthenticationProvider.setPasswordEncoder(passwordEncoder());
    myAuthenticationProvider.setUserDetailsService(userService);
    return myAuthenticationProvider;
  }

  @Override
  @Bean
  public AuthenticationManager authenticationManagerBean() throws Exception {
    ProviderManager manager = new ProviderManager(Arrays.asList(myAuthenticationProvider()));
    return manager;
  }

  @Bean
  RoleHierarchy roleHierarchy() {
    RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
    hierarchy.setHierarchy("ROLE_admin > ROLE_user");
    return hierarchy;
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    // 开启权限配置
    http.authorizeRequests()
        .antMatchers("/vc.jpg").permitAll()
        // 所有的请求都要认证之后 才能访问
        .antMatchers("/admin/**").hasRole("admin")
        .antMatchers("/user/**").hasRole("user")
        .anyRequest().authenticated()
        .and()
        // 开启表单登录配置
        .formLogin()
        .authenticationDetailsSource(myWebAuthenticationDetailsSource)
        .usernameParameter("uname")
        .passwordParameter("passwd")
        .loginProcessingUrl("/doLogin")
        .defaultSuccessUrl("/hello", true)
        // 登录页面地址
        .loginPage("/mylogin.html")
        .permitAll()
        .and()
        .rememberMe()
        .and()
        // 禁用 CSRF 防御功能
        .csrf().disable()
        .sessionManagement()
        .sessionFixation().migrateSession()
        .maximumSessions(1)
        //.maxSessionsPreventsLogin(true)
        ;
  }
  @Bean
  HttpSessionEventPublisher httpSessionEventPublisher() {
    return new HttpSessionEventPublisher();
  }
}
